package com.game.game;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class Test {
	public static void main(String args[]){
		long startTime = System.currentTimeMillis();
		Test test = new Test();
		ArrayList<Integer> hunList = new ArrayList<>();
		hunList.add(24);
		hunList.add(25);
		
		int[] mjArray = new int[]{11,12,13, 23,22,23, 24 , 35,36,37, 43,43,43};
		int drawCard = 25;
		
		System.out.println(test.testHu(mjArray, hunList, drawCard));
		
		long costTime = System.currentTimeMillis() - startTime;
		
		System.out.println("耗时：" + costTime + "毫秒");
//		ArrayList<Integer> testList = new ArrayList<>();
//		testList.add(43);
//		testList.add(45);
//		testList.add(44);
//		testList.add(45);
	
//		System.out.println(test.getOneNeedHunCount(testList, 0));
	}
	
	public int needHunCount = 6;
	public boolean testHu(int[] mjArray,ArrayList<Integer> hunList,int drawCard){
		int needHunCount = 0;
		int[] tmpArr = new int[mjArray.length + (drawCard > 0 ? 1:0)];
		System.arraycopy(mjArray, 0, tmpArr, 0, mjArray.length);
		if(drawCard > 0){
			tmpArr[tmpArr.length - 1] = drawCard;
		}
		
		Map<Integer, ArrayList<Integer>> sptMap = seprateMj(tmpArr,hunList);
		
		int currentHunCount = sptMap.get(0) == null ? 0 : sptMap.get(0).size();
		//每个类型组成一幅需要的混的个数
		Map<Integer, Integer> needhunCountMap = new HashMap<>();
		getAllNeedHunCount(needhunCountMap , sptMap);
		
		boolean isHu = false;
		
		//分情况判断 第一种情况 将在万中 
		needHunCount = needhunCountMap.get(2) + needhunCountMap.get(3)+
				needhunCountMap.get(4) + needhunCountMap.get(5);
		if(needHunCount <= currentHunCount){
			int hasHunNum = currentHunCount - needHunCount;
			isHu = canHu(hasHunNum,sptMap.get(1));
			if(isHu){
				return true;
			}
		}
		
		//第2种情况 将在条中 
		needHunCount = needhunCountMap.get(1) + needhunCountMap.get(3)+
				needhunCountMap.get(4) + needhunCountMap.get(5);
		if(needHunCount <= currentHunCount){
			int hasHunNum = currentHunCount - needHunCount;
			isHu = canHu(hasHunNum,sptMap.get(2));
			if(isHu){
				return true;
			}
		}
		
		//第3种情况 将在桶中 
		needHunCount = needhunCountMap.get(1) + needhunCountMap.get(2)+
				needhunCountMap.get(4) + needhunCountMap.get(5);
		if(needHunCount <= currentHunCount){
			int hasHunNum = currentHunCount - needHunCount;
			isHu = canHu(hasHunNum,sptMap.get(3));
			if(isHu){
				return true;
			}
		}
		
		//第4种情况 将在风中 
		needHunCount = needhunCountMap.get(1) + needhunCountMap.get(2)+
				needhunCountMap.get(3) + needhunCountMap.get(5);
		if(needHunCount <= currentHunCount){
			int hasHunNum = currentHunCount - needHunCount;
			isHu = canHu(hasHunNum,sptMap.get(4));
			if(isHu){
				return true;
			}
		}
		
		//第5种情况 将在ZFB中 
		needHunCount = needhunCountMap.get(1) + needhunCountMap.get(2)+
				needhunCountMap.get(3) + needhunCountMap.get(4);
		if(needHunCount <= currentHunCount){
			int hasHunNum = currentHunCount - needHunCount;
			isHu = canHu(hasHunNum,sptMap.get(5));
			if(isHu){
				return true;
			}
		}
		
		return false;
	}
	/**
	 * 能否凑成整副一将
	 * @param hasHunNum
	 * @param arrayList
	 * @return
	 */
	private boolean canHu(int hunNum, ArrayList<Integer> arrayList) {
		// TODO Auto-generated method stub
		ArrayList<Integer> tempArray = new ArrayList<>();
		if(arrayList != null){
			tempArray.addAll(arrayList);
		}
		
		int arrLen = tempArray.size();
		
		if(arrLen <= 0){
			if(hunNum >= 2){
				return true;
			}
			return false;
		}
		
		for(int i= 0; i< arrLen;i++){
			if(i == arrLen - 1){//最后一张牌
				if(hunNum > 0){
					int tmp = tempArray.get(i);
					hunNum -= 1;
					tempArray.remove(i);
					needHunCount = 6;
					getOneNeedHunCount(tempArray, 0);
					if(needHunCount <= hunNum){
						return true;
					}
					hunNum += 1;
					tempArray.add(tmp);
					Collections.sort(tempArray);
				}
			}
			else{
				if(i+2 == arrLen || tempArray.get(i) % 10 != tempArray.get(i+2) % 10){
					if(test2Combine(tempArray.get(i), tempArray.get(i+1))){
						int tem1 = tempArray.remove(i);
						int tem2 = tempArray.remove(i);
						
						needHunCount = 6;
						getOneNeedHunCount(tempArray, 0);
						if(needHunCount <= hunNum){
							return true;
						}
						tempArray.add(tem1);
						tempArray.add(tem2);
						Collections.sort(tempArray);
					}
				}
				
				if(hunNum > 0 && tempArray.get(i) % 10 != tempArray.get(i+1) % 10){
					hunNum -= 1;
					int tmp = tempArray.remove(i);
					needHunCount = 6;
					getOneNeedHunCount(tempArray, 0);
					if(needHunCount <= hunNum){
						return true;
					}
					hunNum += 1;
					tempArray.add(tmp);
					Collections.sort(tempArray);
				}
			}
		}
		return false;
	}

	/**
	 * 获取每个类型需要的混的个数
	 * @param needhunCountMap
	 * @param sptMap
	 */
	private void getAllNeedHunCount(Map<Integer, Integer> needhunCountMap, Map<Integer, ArrayList<Integer>> sptMap) {
		for(int i = 1;i<= 5;i++){
			needHunCount = 6;
			needhunCountMap.put(i, getOneNeedHunCount(sptMap.get(i),0));
		}
	}
	/**
	 * 获取一种类型需要的混儿数量
	 * @param arrayList
	 * @param hunNum
	 * @return
	 */
	private Integer getOneNeedHunCount(ArrayList<Integer> arrayList, int hunNum) {

		if(needHunCount == 0){
			return needHunCount;
		}
		if(hunNum >= needHunCount){
			return needHunCount;
		}
		
		int length = arrayList == null ? 0: arrayList.size();
		if(length == 0){
			needHunCount = Math.min(hunNum, needHunCount);
			return needHunCount;
		}
		else if(length == 1){
			needHunCount = Math.min(hunNum + 2, needHunCount);
			return needHunCount;
		}else if(length == 2){
			 int type = arrayList.get(0) / 10;
			 int value0 = arrayList.get(0) % 10;
			 int value1 = arrayList.get(1) % 10;
			 //东南西北风 中发白 没有顺子
			 if(type == 4 || type == 5){
				 if(value0 == value1){
					 needHunCount = Math.min(hunNum + 1, needHunCount);
					 return needHunCount;
				 }else {
					needHunCount = Math.min(hunNum+4, needHunCount);
					return needHunCount;
				}
			 }
			 //是 万条筒的时候 能两张牌能凑成对子或者顺子都可以
			 else if(type < 4){
				 if((value1 - value0) < 3){
					 needHunCount = Math.min(hunNum+1, needHunCount);
					 return needHunCount;
				 }else {
					 needHunCount = Math.min(hunNum+4, needHunCount);
					 return needHunCount;
				}
			 }
		}else if(length >= 3){
			
			int type = arrayList.get(0) /10;
			int value0 = arrayList.get(0) % 10;
			int value1 = arrayList.get(1) % 10;
			int value2 = arrayList.get(2) % 10;
			
			
			// 第一个自己一副
			if (hunNum + 2 < needHunCount){
				int tmp = arrayList.remove(0);
				getOneNeedHunCount(arrayList, hunNum + 2);
				arrayList.add(tmp);
				Collections.sort(arrayList);
			}
			
			// 第一个和其他的一个一副
			if(hunNum + 1 < needHunCount){
				if(type == 4 || type == 5){
					if(value0 == value1){
						int tmp1 = arrayList.remove(0);
						int tmp2 = arrayList.remove(0);
						
						getOneNeedHunCount(arrayList, hunNum + 1);
						
						arrayList.add(tmp1);
						arrayList.add(tmp2);
						Collections.sort(arrayList);
					}
				}
				else{
					int arrLen = arrayList.size();
					for(int i = 1;i<arrayList.size();i++){
						if(hunNum + 1 >= needHunCount){
							break;	
						}
						value1 = arrayList.get(i) % 10;
						//455567这里可结合的可能为 45 46 否则是45 45 45 46
						//如果当前的value不等于下一个value则和下一个结合避免重复
						if(i+1 != arrLen){
							value2 = arrayList.get(i+1) % 10;
							if(value1 == value2){
								continue;
							}
						}
						if(value1 - value0 < 3){
							int tmp1 = arrayList.remove(0);
							int tmp2 = arrayList.remove(0);
							
							getOneNeedHunCount(arrayList, hunNum +1);
							arrayList.add(tmp1);
							arrayList.add(tmp2);
							Collections.sort(arrayList);
						}
						else{
							break;
						}
					}
				}
			}
			
			//第一个和其它两个一副
			//后面间隔两张不跟前面一张相同222234 
			//可能性为222 234
			
			int len = arrayList.size();
			for(int i = 1;i< arrayList.size();i++){
				if(hunNum >= needHunCount){
					break;
				}
				value1 = arrayList.get(i) % 10;
				if(i +2 < len){
					if(arrayList.get(i+2) % 10 == value1){
						continue;
					}
				}
				for(int j = i+1;j < arrayList.size(); j++){
					if(hunNum >= needHunCount){
						break;
					}
					value2 = arrayList.get(j) % 10;
					if(j + 1 < len){
						if(arrayList.get(j+1) % 10 == value2){
							continue;
						}
					}
					int temp1 = arrayList.get(0);
					int temp2 = arrayList.get(i);
					int temp3 = arrayList.get(j);
					
					if(test3Combine(temp1,temp2,temp3)){
						arrayList.remove(0);
						arrayList.remove(i-1);
						arrayList.remove(j-2);
						
						getOneNeedHunCount(arrayList, hunNum);
						
						arrayList.add(temp1);
						arrayList.add(temp2);
						arrayList.add(temp3);
						Collections.sort(arrayList);
					}
				}
			}
		}
		return needHunCount;
	}
	
	
	/**
	 * 判断三张牌的组合
	 * @param temp1
	 * @param temp2
	 * @param temp3
	 * @return
	 */
	private boolean test3Combine(int temp1, int temp2, int temp3) {
		int t1 = temp1 / 10;
		int t2 = temp2 / 10;
		int t3 = temp3 / 10;
		
		//牌型不同不能组合
		if(t1 != t2 || t1 != t3){
			return false;
		}
		int v1 = temp1 % 10;
		int v2 = temp2 % 10;
		int v3 = temp3 % 10;
		
		//一样的牌
		if(v1 == v2 && v1 == v3){
			return true;
		}
		
		//下面判断不一样的牌 前面已经判断了不是同一类型就跳过了 这里 这里实际上t1 t2 t3是风或者中发白都返回false
		if(t3 == 4 || t3 == 5){
			return false;
		}
		if((v1 + 1 == v2) && (v2 + 1 == v3)){
			return true;
		}
		return false;
	}
	
	private boolean test2Combine(int card1, int card2){
		int type1 = card1 / 10;
		int type2 = card2 / 10;
		
		int value1 = card1 % 10;
		int value2 = card2 % 10;
		
		if(type1 == type2 && value1 == value2){
			return true;
		}
		return false;
	}

	/**
	 * 将混 万条同风中发白 整合到各自的list中
	 * @param tmpArr
	 * @param hunList
	 * @return
	 */
	private Map<Integer, ArrayList<Integer>> seprateMj(int[] tmpArr, ArrayList<Integer> hunList) {
		Map<Integer, ArrayList<Integer>> sptMap = new HashMap<>();
		for(int i=0 ; i< tmpArr.length;i++){
			if(hunList.contains(tmpArr[i])){
				putIntoSepMap(sptMap,0,tmpArr[i]);
			}else{
				//是万
				if(tmpArr[i] / 10 == 1){
					putIntoSepMap(sptMap,1,tmpArr[i]);
				}
				else if(tmpArr[i] / 10 == 2){//是条
					putIntoSepMap(sptMap,2,tmpArr[i]);
				}
				else if(tmpArr[i] / 10 == 3){//是桶
					putIntoSepMap(sptMap,3,tmpArr[i]);
				}
				else if(tmpArr[i] / 10 == 4){//是风
					putIntoSepMap(sptMap,4,tmpArr[i]);
				}
				else if(tmpArr[i] / 10 == 5){//是zfb
					putIntoSepMap(sptMap,5,tmpArr[i]);
				}
			}
		}
		return sptMap;
	}

	private void putIntoSepMap(Map<Integer, ArrayList<Integer>> sptMap,int type, int i) {
		ArrayList<Integer> arrayList;
		if(!sptMap.containsKey(type)){
			arrayList = new ArrayList<>();
			arrayList.add(i);
			Collections.sort(arrayList);
			sptMap.put(type, arrayList);
		}else{
			arrayList = sptMap.get(type);
			arrayList.add(i);
			Collections.sort(arrayList);
			sptMap.put(type, arrayList);
		}
	}
}
